#include "Part.h"
#include "__regs_base.h"
#include "debug.h"
#include "Mcu.h"
#include "Port.h"
#include "Ea.h"
#include "Mcal_Delay.h"
#include "Mcal_MemLibc.h"
#include "lnk_sym_E3650.h"
#include "e3_device_init.h"
#include "Uart.h"
#if defined(CFG_STARTUP_LP) && defined(CFG_MCULP_MODULE_EN)
#include "McuLp.h"
#endif /* #if defined(CFG_STARTUP_LP) && defined(CFG_MCULP_MODULE_EN)*/
#include "Mcu_Rstgen.h"
#if defined(ENABLE_DMA)
#include "Dma.h"
#endif /* #if defined(ENABLE_DMA) */

#define UART_MODULE_NUM (20U)

#define BM_INTR0_NOISEERR ((uint32)0x01U << 11U)

#define BM_INTR0_BAUDRATEERR ((uint32)0x01U << 10U)

#define BM_INTR0_FRAMEERR ((uint32)0x01U << 9U)

#define BM_INTR0_PARITYERR ((uint32)0x01U << 8U)

#define BM_INTR0_RXFOVF ((uint32)0x01U << 5U)

#define BM_INTR0_RXFUDF ((uint32)0x01U << 3U)

#define UART_BM_INTR_RX_ERROR                                                                                      \
	(BM_INTR0_RXFOVF | BM_INTR0_RXFUDF | BM_INTR0_PARITYERR | BM_INTR0_FRAMEERR | BM_INTR0_BAUDRATEERR |           \
	 BM_INTR0_NOISEERR)

#define UART_INTEN0_OFF 0x30U

#define FSR0_OFF 0x60U

#define BM_FSR0_FULL ((uint32)0x01U << 25U)

#define TXDR_OFF 0x200U

#define FM_FSR1_FILLLVL ((uint32)0xffU << 0U)
#define FV_FSR1_FILLLVL(v) (((uint32)(v) << 0U) & FM_FSR1_FILLLVL)

void uart_rx_handle(uint8 channel, uint8 *data, uint8 len)
{
}

static void es650_debug_enable(void)
{
	uint32 value;

	/* Disable Dual core lock-step enable bit 6 */
	value = readl(0xF8091154UL);
	value &= 0xF7EFDFBFUL;
	writel(value, 0xF8091154UL);
	/* Enable SE and LP core debug ports */
	writel(0xffffU, 0xF07C1600U);
	writel(0x3U, 0xF07C1604U);
	writel(0x3U, 0xF07C1608U);
	/* SE ROM Sticky Bit, bit1 and bit 0 set to 1 */
	value = readl(APB_ROMC_BASE + 0x5CU);
	/* kick se core must set the bit0 and bit1 as 1, 12/20 */
	value |= 1U;
	writel(value, (APB_ROMC_BASE + 0x5CU));

	/* Enable Dual core lock-step enable bit 6 */
	value = readl(0xF8091154UL);
	value |= ~0xF7EFDFBFUL;
	writel(value, 0xF8091154UL);
}

void e3650_init(void)
{
	uint8 coreId = Mcu_GetCoreID();

	if (CPU_INDEX_0 == coreId) {
		es650_debug_enable();
		Mcu_Init(&Mcu_Cfg);
		Mcu_InitClock((Mcu_ClockType)0);
		writel(1, 0xF8C20000UL);
		Port_Init(&Port_Cfg);
	}

#if defined(ENABLE_DMA)
	Dma_Init(&Dma_ConfigRootTable);
#endif /* #if defined(ENABLE_DMA) */
}

void e3650_uart_init(void)
{
	uint32 value;
	uint8 coreId = Mcu_GetCoreID();

	if (CPU_INDEX_0 == coreId) {
		Uart_Init(&Uart_Config);
		Uart_StartRealTimeRecv(CFG_TTY_UART);
		/* Disable Rx error interrupt */
		value = readl(Uart_Config.channelConfigs[CFG_TTY_UART].baseAddr + UART_INTEN0_OFF);
		value &= ~UART_BM_INTR_RX_ERROR;
		writel(value, Uart_Config.channelConfigs[CFG_TTY_UART].baseAddr + UART_INTEN0_OFF);
	}
}

void e3650_start_core(uint32_t cpu, uint32_t addr)
{
	switch (cpu) {
	case KICK_CPU_INDEX_1:
		Mcu_SocKickCore(KICK_CPU_INDEX_1, (uint32)addr);
		break;
	case KICK_CPU_INDEX_2:
		Mcu_SocKickCore(KICK_CPU_INDEX_2, (uint32)addr);
		break;
	case KICK_CPU_INDEX_3:
		Mcu_SocKickCore(KICK_CPU_INDEX_3, (uint32)addr);
		break;
	default:
		break;
	}
}
